package entidades;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Semaphore;

import view.Main;
import view.PanelLog;

public class Processo extends Vertice implements Runnable {

	private String identificador;
	private ArrayList<Recurso> spoolRecursos;
	public Recurso lobjRecurso;
	public boolean marcadocinza;
	public boolean marcadopreto;
	public boolean deadlock;
	public boolean vivo = true;
	public static Semaphore mutexExclusao = new Semaphore(1);

	public Processo(final String identificador, int dS, int dU) {
		super(identificador, 2, dS, dU, "");
		this.identificador = identificador;
		spoolRecursos = new ArrayList<Recurso>();
	}

	public String getIdentificador() {
		return identificador;
	}

	public void setIdentificador(String identificador) {
		this.identificador = identificador;
	}

	public ArrayList<Recurso> getSpoolRecursos() {
		return spoolRecursos;
	}

	public void setSpoolRecursos(ArrayList<Recurso> spoolRecursos) {
		this.spoolRecursos = spoolRecursos;
	}

	public Recurso buscarRecurso() {
		Random random = new Random();
		while (true) {
			int id = Math.abs(random.nextInt() % (Sistema.recursos.size()));
			if (!spoolRecursos.contains(Sistema.buscarRecurso(id))) {
				Recurso lobjRecurso = Sistema.buscarRecurso(id);
				return lobjRecurso;
			}
		}
	}

	public void run() {
		try {
			while (vivo) {

				deadlock = false;
				Thread.sleep(1000);

				tempoDecS -= 1;

				mutexExclusao.acquire();
				if (tempoDecS <= 0 && spoolRecursos.size() < Sistema.recursos.size()) {
					mutexExclusao.release();
					lobjRecurso = buscarRecurso();

					mutexExclusao.acquire();
					Main.getInstance().SolicitaRecurso(this, lobjRecurso);
					Main.mutexLog.acquire();
					PanelLog.logTxt.setText("O processo " + getIdentificador() + " solicitou o recurso " + lobjRecurso.getIdentificador() + "\n"+ PanelLog.logTxt.getText());
					Main.mutexLog.release();
					this.setStatus("Esperando");
					Sistema.grafo.addEdge(this, lobjRecurso);
					mutexExclusao.release();

					lobjRecurso.requisitarPosse(this);
					
					if (!vivo) {
						lobjRecurso.liberar(this);
						break;
					}else{
						mutexExclusao.acquire();
						lobjRecurso.tempoDecU = tempoUtilizacao;
						spoolRecursos.add(lobjRecurso);

						
						mutexExclusao.release();

						Sistema.grafo.removeEdge(this, lobjRecurso);
						this.setStatus("OK");

						System.out.println(lobjRecurso.getIdentificador());
						Sistema.grafo.addEdge(lobjRecurso, this);
						tempoDecS = tempoSolicitacao;
					}
					
				} else {
					mutexExclusao.release();
				}

				mutexExclusao.acquire();
				if (spoolRecursos.size() > 0) {

					for (int i = 0; i < spoolRecursos.size(); i++) {

						if (spoolRecursos.get(i).tempoDecU == tempoDecU) {
							Main.mutexLog.acquire();
							PanelLog.logTxt.setText("O processo " + getIdentificador() + " est� utilizando o recurso "+ spoolRecursos.get(i).getIdentificador() + "\n" + PanelLog.logTxt.getText());
							Main.mutexLog.release();
						}

						spoolRecursos.get(i).tempoDecU -= 1;

						if (spoolRecursos.get(i).tempoDecU <= 0) {
							Main.mutexLog.acquire();
							PanelLog.logTxt.setText("O processo " + identificador + " liberou o recurso " + spoolRecursos.get(i).getIdentificador() + "\n"+ PanelLog.logTxt.getText());
							Main.mutexLog.release();
							Main.getInstance().removeRecursoObtido(spoolRecursos.get(i), this);
							Sistema.grafo.removeEdge(spoolRecursos.get(i), this);
							Recurso r = spoolRecursos.remove(i);
							r.liberar(this);
						}
					}
				}
				mutexExclusao.release();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void excluir() {
		try {
			mutexExclusao.acquire();

			for (int i = 0; i < spoolRecursos.size(); i++) {
				Main.getInstance().removeRecursoObtido(spoolRecursos.get(i), this);
				Sistema.grafo.removeEdge(spoolRecursos.get(i), this);
			}

			for (int i = 0; i < spoolRecursos.size(); i++) {
				spoolRecursos.get(i).liberar(this);
				spoolRecursos.remove(i);
				i--;// isso tava faltando mesmo? era só ESSENCIAL!
			}

			if (lobjRecurso != null && getStatus().equals("Deadlock!")) {
				Main.getInstance().removeRecursoSolicitado(this, lobjRecurso);
				Sistema.grafo.removeEdge(this, lobjRecurso);
				//lobjRecurso.liberar(this);
			}

			vivo = false;

			mutexExclusao.release();

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			mutexExclusao.release();
		}
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj != null && obj instanceof Processo){
			return identificador == ((Processo)obj).getIdentificador();
		}
		return false;
	}

}